package ${projectDomain}.imports;

import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.cache.MemoryCache;
import ${projectDomain}.adapter.logger.LoggerImportTaskAdapter;
import ${projectDomain}.cache.CacheEnum;
import ${projectDomain}.core.CommonOperator;
import ${projectDomain}.feign.AttachFeign;
import ${projectDomain}.pojo.bo.BaseBo;
import ${projectDomain}.pojo.bo.logger.imports.task.LoggerImportTaskQueueBo;
import ${projectDomain}.pojo.bo.logger.imports.task.LoggerImportTaskStopQueueBo;
import ${projectDomain}.pojo.dao.logger.imports.task.LoggerImportTaskDataDo;
import ${projectDomain}.pojo.dao.logger.imports.task.LoggerImportTaskUpdateDo;
import ${projectDomain}.pojo.mo.ImportMo;
import ${projectDomain}.utils.BeanUtils;
import ${projectDomain}.utils.ExcelUtils;
import ${projectDomain}.utils.ExcelUtils.ExcelImportBatch;
import com.unswift.exception.CoreException;
import com.unswift.utils.ClassUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.JsonUtils;
import com.unswift.utils.ObjectUtils;

@Service
@Api(value="导入逻辑业务处理类", author = "unswift", date = "2024-01-09", version = "1.0.0")
public class ImportService extends CommonOperator{

	@Autowired
	@ApiField("导出任务记录表公共服务")
	private LoggerImportTaskAdapter loggerImportTaskAdapter;
	
	@ApiField("导入每次拿的数据量大小")
	@Value("${r'${unswift.import.tempDataLimit}'}")
	private int tempDataLimit;
	
	@Autowired
	@ApiField("内存缓存")
	private MemoryCache memoryCache;
	
	@Autowired
	@ApiField("附件feign")
	private AttachFeign attachFeign;
	
	@SuppressWarnings({ "rawtypes" })
	@ApiMethod(value="导入逻辑实现", params=@ApiField("导入队列业务实体"))
	public void imports(LoggerImportTaskQueueBo importBo) {
		try {
			LoggerImportTaskDataDo importTask = loggerImportTaskAdapter.findById(importBo.getId());
			int exeResult=0;
			IImportBusinessService importService=BeanUtils.getBean(ClassUtils.forName(importTask.getImportBeanClass()));
			try {
				updateStatus(importTask.getId(), 1, importTask.getCreateUser());
				BaseBo bo=JsonUtils.toJava(importTask.getImportData(), ClassUtils.forName(importTask.getImportModelClass()));
				byte[] fileByteArray=attachFeign.downloadByte(ClassUtils.get(bo, "attachUrl")).toBody().getAttachContent();
				Workbook workbook = ExcelUtils.load(new ByteArrayInputStream(fileByteArray));
				Class<?> module=importService.getModule();
				int titleIndex=1;
				ExcelUtils.read(workbook, module, titleIndex, new ExcelImportBatch(tempDataLimit) {
					
					@ApiField("是否初始化")
					private boolean init=false;
					
					@Override
					@SuppressWarnings("unchecked")
					@ApiMethod(value="验证导入行数据", params = {@ApiField("行数据"), @ApiField("数据在excel中的行次")})
					public void validate(Object data, int rowIndex) {
						((ImportMo)data).setWebLanguage(importBo.getLanguage());
						if(!init) {
							importService.start();
						}
						importService.validate((ImportMo)data, rowIndex, importBo.getToken(), bo);
						if(!init) {
							updateCount(importTask.getId(), getDataCount(), importTask.getCreateUser());
							init=true;
						}
					}
					
					@Override
					@SuppressWarnings("unchecked")
					@ApiMethod(value="导入数据批量处理，批次数据根据nocos配置确定批次大小", params = {@ApiField("批次数据"), @ApiField("此列表在excel中的开始行次（从零开始）")})
					public void handleBatch(List<?> dataList, int startRowIndex) {
						if(isStop(importBo.getId())) {
							throw ExceptionUtils.message("import.stop.task");
						}
						for (Object data : dataList) {
							((ImportMo)data).setWebLanguage(importBo.getLanguage());
						}
						importService.handleBatch(dataList, startRowIndex, importBo.getToken(), bo);
						updateProgress(importTask.getId(), new BigDecimal(5+(startRowIndex+dataList.size()-(titleIndex+1))*95.0/getDataCount()).setScale(2, RoundingMode.HALF_UP), importTask.getCreateUser());
					}
				});
				updateStatus(importTask.getId(), 2, importTask.getCreateUser());
				exeResult=1;
			} catch (CoreException e) {
				updateError(importTask.getId(), e.getMessage(), ExceptionUtils.getStackTrace(e), importTask.getCreateUser());
				throw e;
			} catch (Exception e) {
				e.printStackTrace();
				updateError(importTask.getId(), e.getMessage(), ExceptionUtils.getStackTrace(e), importTask.getCreateUser());
				throw ExceptionUtils.exception("import.adapter.exception", e, e.getMessage());
			} finally {
				importService.finish(importBo.getToken());
				complateTask(importTask.getId(), exeResult, importTask.getCreateUser());
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage(), e);
		}
	}
	
	@ApiMethod(value="停止任务", params=@ApiField("停止导入队列业务实体"))
	public void stop(LoggerImportTaskStopQueueBo stopBo) {
		LoggerImportTaskDataDo importTask = loggerImportTaskAdapter.findById(stopBo.getId());
		if(importTask.getStatus()!=2) {//还没有结束就结束
			memoryCache.setHash(CacheEnum.IMPORT_STOP.getKey(), importTask.getId()+"", true);
		}
	}
	
	private boolean isStop(long taskId) {
		Boolean stop=memoryCache.getHash(CacheEnum.IMPORT_STOP.getKey(), taskId+"");
		return ObjectUtils.isNotEmpty(stop) && stop;
	}
	
	@ApiMethod(value="更新任务状态", params = {@ApiField("主键"), @ApiField("状态{0:等待导出,1:导出中,2:导出完成)}"), @ApiField("操作人")})
	private void updateStatus(long id, int status, long changeUserId) {
		LoggerImportTaskUpdateDo update=new LoggerImportTaskUpdateDo();
		update.setId(id);
		update.setStatus((byte)status);
		update.setChangeUser(changeUserId);
		loggerImportTaskAdapter.update(update, false);
	}
	
	@ApiMethod(value="更新导入数量", params = {@ApiField("主键"), @ApiField("导入总数量"), @ApiField("操作人")})
	private void updateCount(long id, long count, long changeUserId) {
		LoggerImportTaskUpdateDo update=new LoggerImportTaskUpdateDo();
		update.setId(id);
		update.setImportCount(count);
		update.setChangeUser(changeUserId);
		loggerImportTaskAdapter.update(update, false);
	}
	
	@ApiMethod(value="更新任务进度", params = {@ApiField("主键"), @ApiField("进度{0-100)}"), @ApiField("操作人")})
	private void updateProgress(long id, BigDecimal progress, long changeUserId) {
		LoggerImportTaskUpdateDo update=new LoggerImportTaskUpdateDo();
		update.setId(id);
		update.setProgress(progress);
		update.setChangeUser(changeUserId);
		loggerImportTaskAdapter.update(update, false);
	}
	
	@ApiMethod(value="更新错误信息", params = {@ApiField("主键"), @ApiField("消息"), @ApiField("堆栈消息"), @ApiField("操作人")})
	private void updateError(long id, String message, String stackMessage, long changeUserId) {
		LoggerImportTaskUpdateDo update=new LoggerImportTaskUpdateDo();
		update.setId(id);
		update.setResult((byte)0);
		if(ObjectUtils.isNotEmpty(message) && message.length()>1000) {
			message=message.substring(0, 1000);
		}
		update.setErrorMessage(message);
		update.setErrorStack(stackMessage);
		update.setChangeUser(changeUserId);
		loggerImportTaskAdapter.update(update, false);
	}
	
	@ApiMethod(value="更新任务状态", params = {@ApiField("主键"), @ApiField("状态{0:等待导出,1:导出中,2:导出完成)}"), @ApiField("操作人")})
	private void complateTask(long id, int result, long changeUserId) {
		LoggerImportTaskUpdateDo update=new LoggerImportTaskUpdateDo();
		update.setId(id);
		update.setStatus((byte)2);
		update.setProgress(new BigDecimal(100));
		update.setResult((byte)result);
		update.setEndTime(new Date());
		update.setChangeUser(changeUserId);
		loggerImportTaskAdapter.update(update, false);
	}
}
